home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / X11 / xconq / util.c < prev    next >
C/C++ Source or Header  |  1995-05-09  |  6KB  |  251 lines

  1. /* Copyright (c) 1987, 1988  Stanley T. Shebs, University of Utah. */
  2. /* This program may be used, copied, modified, and redistributed freely */
  3. /* for noncommercial purposes, so long as this notice remains intact. */
  4.  
  5. #pragma comment(exestr, "@(#) util.c 12.1 95/05/09 ")
  6.  
  7. /* RCS $Header: util.c,v 1.2 88/07/15 16:04:31 shebs Exp $ */
  8.  
  9. /* Random utilities not classifiable elsewhere. Most are not xconq-specific. */
  10.  
  11. #include "config.h"
  12. #include "misc.h"
  13. #include "dir.h"
  14.  
  15. char ordnum[BUFSIZE];           /* buffer for ordinal numbers */
  16. char pluralbuf[BUFSIZE];        /* buffer for plurals of words */
  17.  
  18. int dirx[] = DIRX, diry[] = DIRY;  /* arrays for dir-to-delta conversion */
  19.  
  20. /* This generates a file name in wherever xconq keeps its assorted files. */
  21. /* Note that for Unix machines, XCONQLIB should have a trailing slash. */
  22.  
  23. make_pathname(path, name, extn, pathbuf)
  24. char *path, *name, *extn, *pathbuf;
  25. {
  26. #ifdef UNIX
  27.     sprintf(pathbuf, "%s/%s%s%s",
  28.         ((path && strlen(path) > 0) ? path : "."),
  29.         name,
  30.         ((extn && strlen(extn) > 0) ? "." : ""),
  31.         ((extn && strlen(extn) > 0) ? extn : ""));
  32. #endif /* UNIX */
  33. #ifdef ATARI
  34.     sprintf(pathbuf, "%s\\%s.%s", path, name, extn);
  35. #endif /* ATARI */
  36. }
  37.  
  38. /* Remove a saved game from the system. */
  39.  
  40. remove_saved_game()
  41. {
  42. #ifdef UNIX
  43.     unlink(SAVEFILE);
  44. #endif /* UNIX */
  45. }
  46.  
  47. #ifndef SCO_UNIX    /* nap() defined in libx */
  48.  
  49. /* Napping is like sleeping, but maybe shorter.  Arg is milliseconds. */
  50.  
  51. nap(t)
  52. long t;
  53. {
  54. #ifdef UNIX
  55. #ifdef BSD
  56.     usleep(t*1000);
  57. #endif /* BSD */
  58. #ifndef BSD
  59.     if (t >= 1000) sleep(t/1000);
  60. #endif /* BSD */
  61. #endif /* UNIX */
  62. }
  63. #endif /* !SCO_UNIX */
  64.  
  65. /* Random number handling is important to game but terrible/nonexistent */
  66. /* in some systems.  Do it ourselves and hope it's better... */
  67.  
  68. long randstate;           /* The random state *must* be at least 32 bits. */
  69.  
  70. /* Seed can come from elsewhere, for repeatability.  Otherwise, it comes */
  71. /* the current time, scaled to a point where 32-bit arithmetic won't */
  72. /* overflow.  Pid is not so good, usually a smaller range of values. */
  73.  
  74. init_random(seed)
  75. int seed;
  76. {
  77.     if (seed >= 0) {
  78.     randstate = seed;
  79.     } else {
  80. #ifdef UNIX
  81.     randstate = (time((long *) 0) % 100000L);
  82. #endif /* UNIX */
  83.     }
  84. }
  85.  
  86. /* Numbers lifted from Numerical Recipes, p. 198. */
  87. /* Arithmetic must be 32-bit. */
  88.  
  89. random(m)
  90. int m;
  91. {
  92.     randstate = (8121 * randstate + 28411) % 134456L;
  93.     return ((m * randstate) / 134456L);
  94. }
  95.  
  96. /* Percentage probability, with bounds checking. */
  97.  
  98. probability(prob)
  99. int prob;
  100. {
  101.     if (prob <= 0) return FALSE;
  102.     if (prob >= 100) return TRUE;
  103.     return (random(100) < prob);
  104. }
  105.  
  106. /* Read a line and save it away.  This routine should be used sparingly, */
  107. /* since the malloced space is never freed. */
  108.  
  109. char *
  110. read_line(fp)
  111. FILE *fp;
  112. {
  113.     char tmp[BUFSIZE], *line;
  114.  
  115.     fgets(tmp, BUFSIZE-1, fp);
  116.     tmp[strlen(tmp)-1] = '\0';
  117.     line = (char *) malloc(strlen(tmp)+2);
  118.     strcpy(line, tmp);
  119.     return line;
  120. }
  121.  
  122. /* Copy to new-allocated space.  Again, the new space is never freed. */
  123.  
  124. char *
  125. copy_string(str)
  126. char *str;
  127. {
  128.     char *rslt;
  129.  
  130.     rslt = (char *) malloc(strlen(str)+1);
  131.     strcpy(rslt, str);
  132.     return rslt;
  133. }
  134.  
  135. /* Computing distance in a hexagonal system is a little peculiar, since it's */
  136. /* sometimes just delta x or y, and other times is the sum.  Basically there */
  137. /* are six ways to compute distance, depending on the hextant we're in. */
  138.  
  139. distance(x1, y1, x2, y2)
  140. int x1, y1, x2, y2;
  141. {
  142.     int dx = x2 - x1, dy = y2 - y1;
  143.  
  144.     if (dx >= 0) {
  145.     if (dy >= 0) {
  146.         return (dx + dy);
  147.     } else if ((0 - dy) <= dx) {
  148.         return dx;
  149.     } else {
  150.         return (0 - dy);
  151.     }
  152.     } else {
  153.     if (dy <= 0) {
  154.         return (0 - (dx + dy));
  155.     } else if (dy <= (0 - dx)) {
  156.         return (0 - dx);
  157.     } else {
  158.         return dy;
  159.     }
  160.     }
  161. }
  162.  
  163. /* Convert any vector into a direction (not necessarily the closest one). */
  164. /* Fail horribly on zero vectors. */
  165.  
  166. find_dir(dx, dy)
  167. int dx, dy;
  168. {
  169.     if (dx < 0) {
  170.     if (dy < 0) return SW;
  171.     if (dy == 0) return WEST;
  172.     return NW;
  173.     } else if (dx == 0) {
  174.     if (dy > 0) return NE;
  175.     if (dy == 0) abort();
  176.     return SW;
  177.     } else {
  178.     if (dy < 0) return SE;
  179.     if (dy == 0) return EAST;
  180.     return NE;
  181.     }
  182. }
  183.  
  184. /* Given a number, figure out what suffix should go with it. */
  185. /* Note the use of static storage (to save a little mallocing) */
  186.  
  187. char *
  188. ordinal(n)
  189. int n;
  190. {
  191.     char *suff;
  192.  
  193.     if (n % 100 == 11 || n % 100 == 12 || n % 100 == 13) {
  194.     suff = "th";
  195.     } else {
  196.     switch (n % 10) {
  197.     case 1:   suff = "st"; break;
  198.     case 2:   suff = "nd"; break;
  199.     case 3:   suff = "rd"; break;
  200.     default:  suff = "th"; break;
  201.     }
  202.     }
  203.     sprintf(ordnum, "%d%s", n, suff);
  204.     return ordnum;
  205. }
  206.  
  207. /* Pluralize a word, attempting to be smart about various possibilities */
  208. /* that don't have a different plural form (such as "Chinese" and "Swiss"). */
  209. /* There should probably be a test for when to add "es" instead of "s". */
  210.  
  211. char *
  212. plural_form(word)
  213. char *word;
  214. {
  215.     char endch = ' ', nextend = ' ';
  216.  
  217.     if (strlen(word) > 0) endch   = word[strlen(word)-1];
  218.     if (strlen(word) > 1) nextend = word[strlen(word)-2];
  219.     if (endch == 'h' || endch == 's' || (endch == 'e' && nextend == 's')) {
  220.     sprintf(pluralbuf, "%s", word);
  221.     } else {
  222.     sprintf(pluralbuf, "%ss", word);
  223.     }
  224.     return pluralbuf;
  225. }
  226.  
  227. /* Get a *numeric* index into a string (more useful than ptr to xconq). */
  228. /* Return -1 on failed search. */
  229.  
  230. iindex(ch, str)
  231. char ch, *str;
  232. {
  233.     int i;
  234.  
  235.     if (str == NULL) return (-1);
  236.     for (i = 0; str[i] != '\0'; ++i) if (ch == str[i]) return i;
  237.     return (-1);
  238. }
  239.  
  240. /* This little routine goes at the end of all switch statements on internal */
  241. /* data values.  We want a core dump to debug. */
  242.  
  243. case_panic(str, var)
  244. char *str;
  245. int var;
  246. {
  247.     fprintf(stderr, "Panic! Unknown %s %d\n", str, var);
  248.     abort();
  249. }
  250.  
  251.